<template>
  <div class="search-tree" v-clickoutside="closeTree">
    <div @click="show">
      <slot name="content">
        <div
          class="input-text"
          :class="[searchText === '' ? 'placeholder' : '']"
        >
          {{ searchText || $t('common.base.pleaseSelect') }}
          <div
            @click.stop="handleClear"
            v-show="searchText && clearable"
            class="el-icon el-icon-close"
          ></div>
          <div
            v-show="!clearable || !searchText"
            class="el-icon el-icon-arrow-down"
          ></div>
        </div>
      </slot>
    </div>
    <div class="tree-wrap" v-show="treeShow">
      <el-input
        clearable
        :placeholder="$t('common.connector.searchApp')"
        v-model="filterText"
        @focus="isOpen = true"
        ref="select-tree-input"
        class="search-input"
      ></el-input>
      <div class="tree-wrapper">
        <el-tree
          @node-click="handleNodeClick"
          :data="treeData"
          :props="defaultProps"
          :node-key="defaultProps.key"
          :filter-node-method="filterNode"
          :default-expand-all="false"
          :highlight-current="true"
          :accordion="false"
          ref="tree"
          class="filter-tree"
        ></el-tree>
      </div>
    </div>
  </div>
</template>

<script>
import _ from 'lodash'
import Clickoutside from '@src/util/clickoutside'
/** 睡眠函数*/
const sleep = (time = 1000) =>
  new Promise(resolve => setTimeout(resolve, time));

export default {
  name: 'search-tree',
  props: {
    defaultProps: {
      type: Object,
      default: () => ({
        children: 'children',
        label: 'label',
        key: 'id'
      })
    },
    treeData: {
      type: Array,
      default: () => []
    },
    currentNodeKey: {
      type: String,
      default: null
    },
    clearable: {
      type: Boolean,
      default: false
    },
    isOutsideClickShow: {
      type: Boolean,
      default: false
    },
    isTrigger: {
      type: Boolean,
      default: false
    },
    defaultSearchText: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      treeShow: false,
      filterText: '',
      searchText: '',
      isOpen: true, //  控制 tree-select 关闭的条件之一
    };
  },
  directives: { Clickoutside },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    },
    isOpen(newV) {
      if (newV !== true) {
        setTimeout(() => {
          this.$refs['select-tree-input'].focus();
        }, 200);
      }
    },
    currentNodeKey(newV) {
      if (!newV) {
        this.searchText = '';
      }
    },
    treeData: {
      handler(newV) {
        if(this.isTrigger && newV.length) {
          if (this.currentNodeKey) {
            this.$nextTick(() => {
              this.$refs['tree'].setCurrentKey(this.currentNodeKey);
              const nodeObj = this.$refs['tree'].getCurrentNode() || {};
              // console.log('currentNodeKey nodeObj: ', nodeObj)
              let name = nodeObj[this.defaultProps['label']] || '';
              if(name.indexOf('/') == -1) {
                const parentName = this.getParentName(nodeObj.id)
                name = parentName ? `${parentName}/${name}` : name;
              }
              this.searchText = this.defaultSearchText || name;
              this.filterText = '';
              this.$refs.tree.filter('');
            });
          } else {
            this.filterText = this.searchText = '';
          }
        }
      },
      immediate: true
    },
  },
  methods: {
    closeTree() {
      this.treeShow = false;
    },
    //  树形选择目标链表
    filterNode(value, data, node) {
      if (!value) return true;
      const label = this.defaultProps.label;
      const labelData = [
        data[label],
        node?.parent?.data?.[label],
        node?.parent?.parent?.data?.[label],
        node?.parent?.parent?.parent?.data?.[label]
      ];
      return labelData.slice(0, node.level).some(labelValues => labelValues?.indexOf(value) !== -1);
    },

    handleNodeClick(_data, node) {
      if(this.isTrigger) {
        const data = _.cloneDeep(_data)
        if(data?.bizType === 'directory' && !data?.children?.length) return this.$message.warning('不支持选择目录！')
        const children = data && data[this.defaultProps.children]
        if (data && !children?.length) {
          this.handleTreeStatus(false);
          let name = data.name
          if(name.indexOf('/') == -1) {
            // const parentName = this.getParentName(data.id)
            const parentName = node.parent?.data?.name
            this.$emit('changeParent', node.parent?.data)
            name = parentName ? `${parentName}/${name}` : name;
            data.name = name 
          }
          this.searchText = name;
          this.$emit('select', { ...data });
        }
      } else {
        this.isOpen = false;
        if (_data && !_data[this.defaultProps.children]) {
          this.handleTreeStatus(false);
          this.$emit('select', { ..._data });
        }
      }
    },
    getParentName(nodeId, nodes = this.treeData) {
      for (const node of nodes) {
        if (node.id === nodeId) {
          return this.getParentNameRecursive(node, this.treeData);
        }
        if (node.children && node.children.length > 0) {
          const parentName = this.getParentName(nodeId, node.children);
          if (parentName) {
            return parentName;
          }
        }
      }
      return '';
    },
    getParentNameRecursive(node, nodes) {
      for (const currNode of nodes) {
        if (currNode.children && currNode.children.length > 0) {
          if (currNode.children.includes(node)) {
            return currNode.name;
          }
          const parentName = this.getParentNameRecursive(node, currNode.children);
          if (parentName) {
            return parentName;
          }
        }
      }
      return '';
    },
    show() {
      
      if (this.isOutsideClickShow) {
        this.$emit('insideClick');
        return
      }
      
      this.handleTreeStatus(!this.treeShow);
      
    },
    /** 处理 tree 面板状态 显示|隐藏 */
    handleTreeStatus(status = false) {
      this.treeShow = status;
      if (status === true) {
        this.$nextTick(() => {
          this.$refs['select-tree-input'].focus();
        });
      }
    },

    async sleepHandleTreeStatus(status) {
      await sleep(200);
      if (this.isOpen) {
        this.handleTreeStatus(status);
      }
    },

    /** 清除选择*/
    handleClear() {
      this.handleTreeStatus(false);
      this.$emit('select', {});
    }
  }
};
</script>

<style lang="scss" scoped>
@import './SearchTree.scss';
</style>
